package handler

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"gitee.com/lanshiren/miniprogram/app/log"
	"gitee.com/lanshiren/miniprogram/app/model"
	"gitee.com/lanshiren/miniprogram/app/service"
	"github.com/gin-gonic/gin"
)

// Secret ...
type Secret struct {
	OSSAccessKeyID string `json:"OSSAccessKeyId"`
	Policy         string `json:"policy"`
	Signature      string `json:"signature"`
}

// GetAccessKey ...
func GetAccessKey(c *gin.Context) {
	c.JSON(200, gin.H{
		"result": NewResultRet("", 200, map[string]interface{}{
			"access_key": Secret{
				OSSAccessKeyID: "LTAI4G2kvoZ6jmie3m4BGWPF",
				Policy:         "eyJleHBpcmF0aW9uIjoiMjAzMi0wOC0xMFQwNjoxNDowNi4yNzZaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjBdXX0=",
				Signature:      "u1rvd9i8RBFo12M88HZP6EXnyAs=",
			},
		}),
	})
	return
}

// HandleAuthCode ...
func HandleAuthCode(c *gin.Context) {
	var authData model.AuthData
	if err := c.BindJSON(&authData); err != nil {
		log.MainLogger.Error(fmt.Sprintf("bind client json to code err: %v", err))
	}
	auRes, err := service.WxJsCode2Session(authData.Code)
	if err != nil {
		c.JSON(500, gin.H{
			"result": NewResultRet(err.Error(), 500, nil),
		})
		return
	}
	fmt.Printf("WX Auth Res: %v", auRes)
	token := ""
	switch auRes.Errcode {
	case 0: // success
		token = service.GenToken(fmt.Sprintf("%s.%s.%s", auRes.Openid, auRes.SessionKey, service.GenRandString(32)))
		// handle register success
		if err := service.SaveSession(3600*24, "session-"+token, auRes.Openid+"$"+auRes.SessionKey); err != nil {
			c.JSON(500, gin.H{
				"result": NewResultRet(err.Error(), 500, nil),
			})
			return
		}
		// Check If User Exist
		var user model.UsersDO
		user, err = service.GetUserByOpenID(auRes.Openid)
		if err != nil {
			// Save Open ID to db
			if err := service.SaveUserOpenID(auRes.Openid); err != nil {
				c.JSON(500, gin.H{
					"result": NewResultRet(err.Error(), 500, map[string]interface{}{
						"token": "",
					}),
				})
			}
		}
		if user.Nickname != "" {
			c.JSON(200, gin.H{
				"result": NewResultRet("", 200, map[string]interface{}{
					"token":    token,
					"userInfo": service.ConvertUserDOToVo(&user),
				}),
			})
			return
		} else {
			c.JSON(200, gin.H{
				"result": NewResultRet("", 200, map[string]interface{}{
					"token": token,
				}),
			})
			return
		}
	case -1:
		c.JSON(500, gin.H{
			"result": NewResultRet("系统繁忙, 请稍候再试", 500, nil),
		})
		return
	case 40029:
		c.JSON(500, gin.H{
			"result": NewResultRet("code 无效", 500, nil),
		})
		return
	case 45011:
		c.JSON(500, gin.H{
			"result": NewResultRet("频率限制，每个用户每分钟100次", 500, nil),
		})
		return
	}
	c.JSON(200, gin.H{
		"result": NewResultRet("", 200, map[string]interface{}{
			"token": token,
		}),
	})
}

// AuthorizedLogin ...
func AuthorizedLogin(c *gin.Context) {
	token := c.Request.Header.Get("token")
	dataRes, _ := service.TryGetUserSession("session-" + token)
	var loginData model.LoginData
	if err := c.BindJSON(&loginData); err != nil {
		log.MainLogger.Error(fmt.Sprintf("bind client json to code err: %v", err))
	}
	// pc := wxbizdatacrypt.WxBizDataCrypt{AppId: config.Conf.AppID, SessionKey: strings.Split(userData, "$")[1]}
	// result, err := pc.Decrypt(loginData.EncryptedData, loginData.Iv, true)
	// if err != nil {
	// 	fmt.Println(err)
	// } else {
	// 	log.MainLogger.Info(result.(string))
	// }
	userInfo := loginData.UserInfoVo
	// err = json.Unmarshal([]byte(result.(string)), &userInfo)
	// commit user info to db
	if err := service.UpdateUserInfo(
		strings.Split(dataRes, "$")[0],
		model.UsersDO{
			Nickname:  userInfo.NickName,
			Gender:    userInfo.Gender,
			City:      userInfo.City,
			AvatarUrl: userInfo.AvatarUrl,
			RoleId:    model.SimpleUser,
		}); err != nil {
		c.JSON(500, gin.H{
			"result": NewResultRet(err.Error(), 500, nil),
		})
		return
	}
	userInfo.RoleID = model.SimpleUser
	userDo, _ := service.GetUserByOpenID(userInfo.OpenId)
	userInfo.Id = strconv.Itoa(int(userDo.ID))
	c.JSON(200, gin.H{
		"result": NewResultRet("", 200, map[string]interface{}{
			"userInfo": userInfo,
		}),
	})
}

// Authorize ...
func Authorize() gin.HandlerFunc {
	return func(c *gin.Context) {
		token := c.Request.Header.Get("token")
		_, err := service.TryGetUserSession("session-" + token)
		if err != nil {
			c.Abort()
			c.JSON(http.StatusUnauthorized, gin.H{"err_msg": "permission denied! please login first"})
			return
		} else {
			c.Next()
		}
	}
}
